package org.anderground.editor.model;

import java.io.File;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;

import org.anderground.core.model.ModelData;
import org.anderground.modules.storage.xml.XmlModelStorage;

/**
 * @author Ilya Shurigyn (honorik@gmail.com)
 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
 */
public class EditorModel extends Observable implements Observer {

	/** singleton instance */
	private static EditorModel model = new EditorModel();

	private ModelData data;

	public void setChanged() {
		super.setChanged();
	}

	/**
	 * private constructor
	 */
	private EditorModel() {
		load(new ModelData());
	}

	/**
	 * @return singleton instance
	 */
	public static EditorModel getInstance() {
		return model;
	}

	/**
	 * @param data
	 */
	public void load(ModelData data) {
		this.data = data;
		data.addObserver(this);
		setChanged();
		notifyObservers();
	}

	@Override
	public void update(Observable o, Object arg) {
		if (o == data) {
			setChanged();
		}
	}

	/**
	 * loads a new model data
	 * 
	 * @param filePath
	 *            the file path to load model from
	 */
	public void load(String filePath) {
		try {
			load(XmlModelStorage.createReader(new File(filePath)).read());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public void save(String filePath) {
		try {
			XmlModelStorage.createWriter(new File(filePath)).write(data);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public ModelData getData() {
		return data;
	}

	public void clear() {

		load(new ModelData());

	}

	// public Station addStation(String name, Coord position,
	// Coord location, Time openTime, Time closeTime) {
	// Station station = new Station(name, position, location, openTime,
	// closeTime, new Station.Label(0, new Point(0, 0), true));
	// performAction(new AddAction(station));
	// return station;
	// }
	//
	// public void removeStations(List<Station> stations) {
	// performAction(new RemoveAction(stations, null));
	// }
	//
	// public void remove(List<Station> stations, List<Tunnel> tunnels) {
	// performAction(new RemoveAction(stations, tunnels));
	// }
	//
	// public void removeTunnel(List<Tunnel> tunnels) {
	// performAction(new RemoveAction(null, tunnels));
	// }
	//
	// public Transfer addTransfer(Station from, Station to, int time) {
	// Transfer transfer = new Transfer(from, to, time);
	// performAction(new AddAction(transfer));
	// return transfer;
	// }
	//
	// public Tunnel addTunnel(Station from, Station to, Line line, int time,
	// boolean smooth) {
	// Tunnel tunnel = new Tunnel(from, to, time, line, smooth);
	// performAction(new AddAction(tunnel));
	//
	// return tunnel;
	// }
	//
	// public void moveStations(List<Station> stations, float dx, float dy) {
	// performAction(new MoveStationsAction(stations, dx, dy));
	// }
	//
	// public void moveStation(Station station, Coord position) {
	// performAction(new MoveStationsAction(station, position));
	// }
	//
	// public void moveStationLabel(Station station, int dx, int dy) {
	// performAction(new MoveStationLabelAction(station, dx, dy));
	// }
	//
	// public void setStationName(Station station, String name) {
	// performAction(new StationNameSetAction(station, name));
	// }
	//
	// public void setStationLocation(Station station, Coord point) {
	// performAction(new StationLocationChangeAction(station, point));
	// }
	//
	// public void setStationTime(Station station, Time open, Time close) {
	// performAction(new StationTimeChangeAction(station, open, close));
	// }
	//
	// public void setTunnelTime(Tunnel tunnel, int time) {
	// performAction(new TunnelTimeChangeAction(tunnel, time));
	//
	// }
	//
	// public void setTransferTime(Transfer transfer, int time) {
	// performAction(new TransferTimeChangeAction(transfer, time));
	//
	// }
	//
	// public void addLine(Line line) {
	// performAction(new AddLineAction(line));
	// }
	//
	// public void setLineName(Line line, String name) {
	// performAction(new LineNameChangeAction(line, name));
	//
	// }
	//
	// public void setLineDelay(Line line, int delay) {
	// performAction(new LineDelayChangeAction(line, delay));
	//
	// }
	//
	// public void setLineColor(Line line, Color color) {
	// performAction(new LineColorChangeAction(line, color));
	//
	// }
	//
	// class MoveStationsAction implements Action {
	//
	// double dx, dy;
	// List<Station> stations;
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// public MoveStationsAction(List<Station> stations, double dx, double dy) {
	// this.stations = stations;
	// this.dx = dx;
	// this.dy = dy;
	// }
	//
	// public MoveStationsAction(Station station, double dx, double dy) {
	// this.stations = new ArrayList<Station>();
	// stations.add(station);
	// this.dx = dx;
	// this.dy = dy;
	// }
	//
	// public MoveStationsAction(Station station, Coord newPosition) {
	// this(station, newPosition.getX() - station.getPosition().getX(),
	// newPosition.getY() - station.getPosition().getY());
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// if (action instanceof MoveStationsAction) {
	// MoveStationsAction t = (MoveStationsAction) action;
	// if (isListEquals(stations, t.stations)) {
	// this.undo();
	// dx += t.dx;
	// dy += t.dy;
	// this.perform();
	// return true;
	// }
	//
	// }
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// for (Station station : stations) {
	// Coord position = station.getPosition();
	// edit(position).setX(position.getX() + (int) dx);
	// edit(position).setY(position.getY() + (int) dy);
	// }
	//
	// }
	//
	// @Override
	// public void undo() {
	// for (Station station : stations) {
	// Coord position = station.getPosition();
	// edit(position).setX(position.getX() - (int) dx);
	// edit(position).setY(position.getY() - (int) dy);
	// }
	// }
	//
	// @SuppressWarnings("unchecked")
	// boolean isListEquals(List list1, List list2) {
	// int i = 0;
	// for (Object o : list1) {
	// if (!list2.contains(o))
	// return false;
	// i++;
	// }
	// if (list2.size() == i)
	// return true;
	// return false;
	// }
	//
	// }
	//
	// class StationLocationChangeAction implements Action {
	//
	// private Coord oldPosition, newPosition;
	// private Station station;
	//
	// public StationLocationChangeAction(Station station, Coord location) {
	// this.newPosition = location;
	// this.oldPosition = station.getLocation();
	// this.station = station;
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// // edit(station).setLocation(newPosition);
	// }
	//
	// @Override
	// public void undo() {
	// // edit(station).setLocation(oldPosition);
	// }
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// }
	//
	// class MoveStationLabelAction implements Action {
	//
	// private int dx, dy;
	// private Station station;
	//
	// public MoveStationLabelAction(Station station, int dx, int dy) {
	// this.dx = dx;
	// this.dy = dy;
	// this.station = station;
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// if (action instanceof MoveStationLabelAction) {
	// MoveStationLabelAction t = (MoveStationLabelAction) action;
	// if (t.getStation() == station) {
	// dx += t.dx;
	// dy += t.dy;
	// return true;
	// }
	// }
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// Point offset = station.getLabel().getOffset();
	// edit(offset).setX(offset.getX() + dx);
	// edit(offset).setY(offset.getY() + dy);
	// }
	//
	// @Override
	// public void undo() {
	// Point offset = station.getLabel().getOffset();
	// edit(offset).setX(offset.getX() - dx);
	// edit(offset).setY(offset.getY() - dy);
	// }
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// Station getStation() {
	// return station;
	// }
	//
	// }
	//
	// class StationNameSetAction implements Action {
	//
	// private String oldName;
	// private String newName;
	// private Station station;
	//
	// public StationNameSetAction(Station station, String name) {
	// this.station = station;
	// oldName = station.getName();
	// newName = name;
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// edit(station).setName(newName);
	// }
	//
	// @Override
	// public void undo() {
	// edit(station).setName(oldName);
	//
	// }
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// }
	//
	// class StationTimeChangeAction implements Action {
	// private Station station;
	// private Time oldOpenTime, oldCloseTime;
	// private Time newOpenTime, newCloseTime;
	//
	// public StationTimeChangeAction(Station station, Time open, Time close) {
	// this.station = station;
	// this.newCloseTime = close;
	// this.newOpenTime = open;
	// this.oldCloseTime = station.getOpenTime();
	// this.oldOpenTime = station.getCloseTime();
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// edit(station).setOpenTime(newOpenTime);
	// edit(station).setCloseTime(newCloseTime);
	// }
	//
	// @Override
	// public void undo() {
	// edit(station).setOpenTime(oldOpenTime);
	// edit(station).setCloseTime(oldCloseTime);
	//
	// }
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// }
	//
	// class TunnelTimeChangeAction implements Action {
	//
	// private Tunnel tunnel;
	// private int oldTime;
	// private int newTime;
	//
	// public TunnelTimeChangeAction(Tunnel tunnel, int time) {
	//
	// this.tunnel = tunnel;
	// newTime = time;
	// oldTime = tunnel.getTime();
	//
	// }
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// edit(tunnel).setTime(newTime);
	// }
	//
	// @Override
	// public void undo() {
	// edit(tunnel).setTime(oldTime);
	// }
	//
	// }
	//
	// class TransferTimeChangeAction implements Action {
	//
	// private Transfer transfer;
	// private int oldTime;
	// private int newTime;
	//
	// public TransferTimeChangeAction(Transfer transfer, int time) {
	//
	// this.transfer = transfer;
	// newTime = time;
	// oldTime = transfer.getTime();
	//
	// }
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	//
	// edit(transfer).setTime(newTime);
	//
	// }
	//
	// @Override
	// public void undo() {
	//
	// edit(transfer).setTime(oldTime);
	//
	// }
	//
	// }
	//
	// class HardScaleAction implements Action {
	//
	// private float scale;
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// @Override
	// public boolean merge(Action arg0) {
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// for (Station station : data.getStations()) {
	// Coord position = station.getPosition();
	// edit(position).setX((int) (position.getX() * scale));
	// edit(position).setY((int) (position.getY() * scale));
	// }
	//
	// }
	//
	// @Override
	// public void undo() {
	// for (Station station : data.getStations()) {
	// Coord position = station.getPosition();
	// edit(position).setX((int) (position.getX() / scale));
	// edit(position).setY((int) (position.getY() / scale));
	// }
	//
	// }
	//
	// }
	//
	// class LineNameChangeAction implements Action {
	//
	// private Line line;
	// private String oldName, newName;
	//
	// public LineNameChangeAction(Line line, String newName) {
	// this.line = line;
	// this.newName = newName;
	// this.oldName = line.getName();
	// }
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// edit(line).setName(newName);
	//
	// }
	//
	// @Override
	// public void undo() {
	// edit(line).setName(oldName);
	// }
	//
	// }
	//
	// class LineDelayChangeAction implements Action {
	//
	// private Line line;
	//
	// private int oldDelay, newDelay;
	//
	// public LineDelayChangeAction(Line line, int delay) {
	// this.line = line;
	// this.oldDelay = line.getTrainDelay();
	// this.newDelay = delay;
	// }
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// edit(line).setTrainDelay(newDelay);
	//
	// }
	//
	// @Override
	// public void undo() {
	// edit(line).setTrainDelay(oldDelay);
	// }
	//
	// }
	//
	// class LineColorChangeAction implements Action {
	//
	// private Line line;
	// private int oldColor, newColor;
	//
	// public LineColorChangeAction(Line line, Color color) {
	// this.line = line;
	// this.oldColor = line.getColor();
	// this.newColor = color.getRGB();
	// }
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// edit(line).setColor(newColor);
	//
	// }
	//
	// @Override
	// public void undo() {
	// edit(line).setColor(oldColor);
	//
	// }
	//
	// }
	//
	// class AddLineAction implements Action {
	//
	// @SuppressWarnings("unused")
	// private Line line;
	//
	// public AddLineAction(Line line) {
	// this.line = line;
	// }
	//
	// @Override
	// public boolean hasDataAffected() {
	// return false;
	// }
	//
	// @Override
	// public boolean merge(Action action) {
	// return false;
	// }
	//
	// @Override
	// public void perform() {
	// // lines.add(line);
	//
	// }
	//
	// @Override
	// public void undo() {
	// // lines.remove(line);
	//
	// }
	//
	// }

}
